package com.gitee.apanlh.web.filter;

import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.config.UriFilterConfig;
import com.gitee.apanlh.web.filter.xss.BaseXssValid;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;

import java.io.IOException;

/**	
 * 	XSSFilter过滤
 * 	<br>启动为第一加载顺序
 * 	<br>适用于单体架构
 * 	<br>如需使用 则继承该类
 * 	
 * 	@author Pan
 */
public abstract class BaseXssFilter implements Filter {
	
	/** 重定向地址 */
	private String redirectPath;
	
	private boolean isXFrameOptions;
	
	private String[] whiteList = new String[0];
	
	/**
	 * 	默认构造函数
	 * 	
	 * 	@author Pan
	 */
	BaseXssFilter() {
		super();
	}
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		Filter.super.init(filterConfig);
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		HttpServletResponse httpResponse = (HttpServletResponse)response;
		
		if (isXFrameOptions && httpResponse.getHeader("X-Frame-Options") == null) {
			httpResponse.addHeader("X-Frame-Options", "SAMEORIGIN");
		}
		
		if (!ValidParam.isEmpty(whiteList)) {
			Log.get().info("未获取到过滤白名单列表!采用默认白名单列表");
		}
		
		if (!UriFilterConfig.filterUri(httpRequest, whiteList)) {
			try {
				//	检测XSS攻击
				if (BaseXssValid.checkXss(httpRequest)) {
					Log.get().error("出现XSS攻击!");
					httpResponse.setStatus(HttpStatus.FORBIDDEN.value());
					return ;
				}
			} catch (Exception e) {
				Log.get().error("checkXss出现错误:{}", e.getMessage(), e);
				httpResponse.setStatus(HttpStatus.FORBIDDEN.value());
				return ;
			}
		}
		//	白名单则放行
		chain.doFilter(httpRequest, httpResponse);
	}

	@Override
	public void destroy() {
		Filter.super.destroy();
	}

	public String getRedirectPath() {
		return redirectPath;
	}

	public void setRedirectPath(String redirectPath) {
		this.redirectPath = redirectPath;
	}

	public boolean hasXFrameOptions() {
		return isXFrameOptions;
	}

	public void setXFrameOptions(boolean isXFrameOptions) {
		this.isXFrameOptions = isXFrameOptions;
	}

	public String[] getWhiteList() {
		return whiteList;
	}

	public void setWhiteList(String[] whiteList) {
		this.whiteList = whiteList;
	}
}
